142 Commits

Author SHA1 Message Date
Jonathan Miller 2a1692d599 fix: resolve code review issues in wiki and status features
Universal: Auto Version Bump / Version Bump (push) Successful in 10s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 36s
Deploy MokoGitea / deploy (push) Successful in 7m31s
- collectWikiPages: store hyphen-normalized names for flexible lookup
- Backlinks: use wiki_service.GitPathToWebPath for subdirectory URLs
- issue_statuses.tmpl: fix garbled em-dash bytes (0x97 → hyphen)
- backlinks.tmpl: fix pluralization text
2026-06-21 17:57:46 -05:00
Jonathan Miller 71d52e432e feat: enforce required baseline issue statuses (#681)
Deploy MokoGitea / deploy (push) Successful in 5m8s
Add IsRequired field to IssueStatusDef. Open and Closed statuses are
seeded as required and cannot be deleted. Delete attempts return an
error flash in the web UI and ErrStatusRequired in the model layer.
API response now includes is_required field.
2026-06-21 11:29:49 -05:00
Jonathan Miller 2b6684536e feat: remove display_name, compute from extension_type + name (#650)
- Remove DisplayName field from RepoMetadata and UpdateStreamConfig
- Add DerivedDisplayName() method: "{Type} - {Name}" (e.g. "Package - MokoSuiteBackup")
- API returns computed display_name in GET, ignores it on PUT
- Update server feeds use DerivedDisplayName() instead of stored value
- Remove display_name from web forms (repo licensing, org update streams)
- License settings API computes display_name from repo metadata
- Migration v358: drop display_name columns from both tables
2026-06-20 10:45:54 -05:00
Jonathan Miller 245b5a8e6a feat(custom-fields): add required flag UI and API validation (#597)
Branch Policy Check / Verify merge target (pull_request) Failing after 4s
Universal: PR Check / Branch Policy (pull_request) Failing after 4s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: PR Check / Validate PR (pull_request) Failing after 15s
Generic: Repo Health / Access control (pull_request) Successful in 5s
Generic: Project CI / Lint & Validate (pull_request) Successful in 1m0s
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 3s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Failing after 1m30s
Universal: Auto Version Bump / Version Bump (push) Successful in 11s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Successful in 2m37s
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Generic: Repo Health / Report Issues (push) Has been cancelled
- Add required checkbox to org custom field settings form
- Show red asterisk (*) indicator on required fields in the list
- Validate required custom fields on API issue create (return 422)
- Add locale strings for required field UI

The Required column already exists in the DB (migration v343) and is
already validated in the web form. This adds the missing org settings
UI checkbox and API-side validation.

Co-Authored-By: Moko Consulting <hello@mokoconsulting.tech>
2026-06-11 21:46:24 -05:00
Jonathan Miller be6f3091af fix: switch org wiki tab to .profile wiki sidecars (#595)
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
Generic: Project CI / Lint & Validate (push) Successful in 35s
Deploy MokoGitea / deploy (push) Failing after 1m16s
Generic: Project CI / Tests (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Generic: Repo Health / Report Issues (push) Has been cancelled
Fixes #594
2026-06-09 15:05:05 -05:00
Jonathan Miller 1caf26453f feat: issue metadata API + org wiki tab with internal/external mode
Generic: Project CI / Tests (push) Blocked by required conditions
Generic: Project CI / Tests (pull_request) Blocked by required conditions
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Universal: PR Check / Report Issues (pull_request) Blocked by required conditions
Generic: Repo Health / Scripts governance (pull_request) Blocked by required conditions
Generic: Repo Health / Repository health (pull_request) Blocked by required conditions
Generic: Repo Health / Report Issues (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Generic: Repo Health / Access control (pull_request) Successful in 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: PR Check / Validate PR (pull_request) Failing after 12s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Successful in 41s
Generic: Project CI / Lint & Validate (pull_request) Successful in 43s
Generic: Project CI / Lint & Validate (push) Successful in 45s
PR RC Release / Build RC Release (pull_request) Failing after 39s
Universal: Build & Release / Build & Release Pipeline (pull_request) Failing after 31s
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Universal: Auto Version Bump / Version Bump (push) Successful in 7s
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Generic: Repo Health / Report Issues (push) Has been cancelled
Issue Status/Priority/Type API:
- Expose status_id, priority_id, type_id (with resolved names) on Issue API struct
- New endpoints: GET /orgs/{org}/issue-statuses, /issue-priorities, /issue-types
- CreateIssue and EditIssue handlers accept status_id, priority_id, type_id
- MCP tools: 5 new tools + updated create/update with metadata params

Org Wiki Tab:
- Convention repos: wiki (public) and wiki-private (members-only)
- Inline wiki rendering with markdown pipeline, sidebar, footer, page list
- Public/private view dropdown (same UX as org profile README selector)
- External wiki mode: link to outside URL from wiki tab
- Wiki mode setting in org settings (internal vs external with URL field)
- Migration 354: add wiki_mode and wiki_url to user table
2026-06-09 10:20:54 -05:00
Jonathan Miller 74279c55e3 fix(licensing): hide require-key option for Joomla update servers
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Generic: Repo Health / Access control (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m25s
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Generic: Repo Health / Report Issues (push) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled
Joomla's update system does not support license key authentication,
so hide the "Require license key for update feeds" checkbox when
the platform is set to Joomla or Joomla+Dolibarr.
2026-06-07 11:38:05 -05:00
Jonathan Miller 2cc4f7c047 feat: org settings for Issue Types + MCP SSE hosted + npm auto-publish
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Generic: Repo Health / Access control (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m9s
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Generic: Repo Health / Report Issues (push) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled
- Org settings page for managing Issue Type definitions (CRUD)
- MCP SSE endpoint deployed at git.mokoconsulting.tech/mcp/
- npm auto-publish workflow on MCP source changes to main
2026-06-06 19:52:55 -05:00
Jonathan Miller 55c2f81c58 feat(issues): org-level priority field with customizable levels (#509)
Generic: Repo Health / Site Health (push) Has been cancelled
Generic: Repo Health / Access control (push) Has been cancelled
Generic: Repo Health / Site Health (pull_request) Has been cancelled
Branch Policy Check / Verify merge target (pull_request) Has been cancelled
PR RC Release / Build RC Release (pull_request) Has been cancelled
Generic: Repo Health / Access control (pull_request) Has been cancelled
Branch Cleanup / Delete merged branch (pull_request) Has been cancelled
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Generic: Repo Health / Report Issues (push) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled
Add org-level issue priority definitions that appear in the issue
sidebar. Each priority has a name, color, sort order, and optional
default flag. Follows the same architecture as custom statuses (#502).

Includes:
- IssuePriorityDef model with CRUD operations
- Migration v348 adding issue_priority_def table + priority_id on issues
- Org settings UI for managing priorities
- Issue sidebar dropdown for selecting priority

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-06 11:52:44 -05:00
Jonathan Miller c568e199ed feat(issues): custom status definitions with automated actions (#502)
Generic: Repo Health / Access control (push) Has been cancelled
Generic: Repo Health / Site Health (push) Has been cancelled
Branch Policy Check / Verify merge target (pull_request) Has been cancelled
Generic: Repo Health / Site Health (pull_request) Has been cancelled
Universal: PR Check / Branch Policy (pull_request) Has been cancelled
Generic: Repo Health / Access control (pull_request) Has been cancelled
PR RC Release / Build RC Release (pull_request) Has been cancelled
Universal: PR Check / Validate PR (pull_request) Has been cancelled
Branch Cleanup / Delete merged branch (pull_request) Has been cancelled
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Generic: Repo Health / Report Issues (push) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled
Add org-level custom issue status definitions that appear in the issue
sidebar. Each status has a name, color, description, and an optional
"closes issue" flag that automatically closes/reopens the issue when
the status is selected.

Includes:
- IssueStatusDef model with CRUD operations
- Migration v346 adding issue_status_def table + status_id on issues
- Org settings UI for managing statuses
- Issue sidebar dropdown for selecting status
- Auto close/reopen when status has closes_issue flag

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-06 08:24:44 -05:00
Jonathan Miller 6bd9548b2a feat(custom-fields): move to org-level definitions with issue and repo scopes
Generic: Repo Health / Site Health (push) Has been cancelled
Generic: Repo Health / Access control (push) Has been cancelled
Branch Policy Check / Verify merge target (pull_request) Has been cancelled
Universal: PR Check / Branch Policy (pull_request) Has been cancelled
Generic: Repo Health / Site Health (pull_request) Has been cancelled
Generic: Repo Health / Access control (pull_request) Has been cancelled
Universal: PR Check / Validate PR (pull_request) Has been cancelled
Branch Cleanup / Delete merged branch (pull_request) Has been cancelled
Universal: Build & Release / Promote to RC (pull_request) Has been cancelled
PR RC Release / Build RC Release (pull_request) Has been cancelled
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Generic: Repo Health / Report Issues (push) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled
- CustomFieldDef now has owner_id (org) and scope (issue/repo)
- Issue sidebar loads fields by org owner_id, not repo_id
- Org Settings > Custom Fields page for managing field definitions
- Repo Settings > Metadata page for filling in repo-scoped values
- Migration v345 adds owner_id, scope, entity_id, entity_type columns
- Per-repo custom field management replaced by org-level
- Replaces .mokogitea/manifest.xml with database-backed metadata

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-04 19:11:22 -05:00
Jonathan Miller ee20006b15 fix(ui): rename "Licensing" to "Update Server" across settings UI
Branch Policy Check / Verify merge target (pull_request) Has been cancelled
Universal: PR Check / Branch Policy (pull_request) Has been cancelled
Generic: Repo Health / Site Health (pull_request) Has been cancelled
Generic: Repo Health / Site Health (push) Has been cancelled
PR RC Release / Build RC Release (pull_request) Has been cancelled
Generic: Repo Health / Access control (pull_request) Has been cancelled
Generic: Repo Health / Access control (push) Has been cancelled
Universal: PR Check / Validate PR (pull_request) Has been cancelled
Branch Cleanup / Delete merged branch (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Generic: Repo Health / Report Issues (push) Has been cancelled
The update server system works without license keys — the primary
feature is serving update feeds. Rename all UI labels from "Licensing"
to "Update Server" to reflect this. License key management remains
under the Licenses tab.

- Repo settings nav: "Licensing & Updates" -> "Update Server"
- Advanced settings toggle: "Enable licensing" -> "Enable Update Server"
- Org settings nav: "Licensing & Update Streams" -> "Update Server"
- Icon changed from octicon-key to octicon-broadcast
- Updated help text to emphasize update feeds over licensing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-04 09:16:49 -05:00
Jonathan Miller ea10e8500c fix(ui): replace invalid octicon-settings with octicon-gear
Branch Policy Check / Verify merge target (pull_request) Has been cancelled
Universal: PR Check / Branch Policy (pull_request) Has been cancelled
Universal: PR Check / Validate PR (pull_request) Has been cancelled
PR RC Release / Build RC Release (pull_request) Has been cancelled
Branch Cleanup / Delete merged branch (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 14:45:37 -05:00
Jonathan Miller eca929f680 feat(licenses): configurable key prefix (#406), header button (#408), open feed button (#409)
Branch Policy Check / Verify merge target (pull_request) Has been cancelled
Universal: PR Check / Branch Policy (pull_request) Has been cancelled
Universal: PR Check / Validate PR (pull_request) Has been cancelled
PR RC Release / Build RC Release (pull_request) Has been cancelled
Branch Cleanup / Delete merged branch (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
#406: Add KeyPrefix field to UpdateStreamConfig. GenerateKeyString
now accepts a prefix parameter, looked up from org config. Default
remains MOKO if not set. Auto-uppercased, max 20 chars.

#408: Move "New Package" button into the packages header bar,
right-aligned. Uses details/summary pattern — clicking the button
expands the create form below. Cleaner layout on both repo and org.

#409: Add open-in-new-tab button (external link icon) next to every
copy button on feed URLs. All four feeds: Joomla XML, Dolibarr JSON,
WordPress JSON, Changelog XML.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 08:51:55 -05:00
Jonathan Miller 2799558040 feat(orgs): enterprise sub-org hierarchy with parent-child relationships (#410)
Branch Policy Check / Verify merge target (pull_request) Has been cancelled
Universal: PR Check / Branch Policy (pull_request) Has been cancelled
Universal: PR Check / Validate PR (pull_request) Has been cancelled
Branch Cleanup / Delete merged branch (pull_request) Has been cancelled
PR RC Release / Build RC Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Add ParentOrgID field to User model for org hierarchy. Parent orgs
can have child orgs, enabling enterprise structures like
MokoConsulting → client orgs.

Model changes:
- ParentOrgID int64 on User (INDEX, DEFAULT 0)
- GetChildOrgs, GetAncestorOrgIDs, GetParentOrg helpers
- Max 10 hierarchy levels with cycle detection

License integration:
- ListLicensePackagesWithAncestors — shows packages from parent orgs
- ListLicenseKeysWithAncestors — shows keys from parent orgs
- SearchLicenseKeysWithAncestors — searches across hierarchy
- Master keys from parent orgs validate for child org repos

UI:
- Parent org dropdown in org settings (owners/admins only)
- Shows all orgs user owns except self

Migration v341: adds parent_org_id column to user table.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 08:14:08 -05:00
Jonathan Miller a149edccd3 feat(licenses): feed visibility modes and login-required releases
Add FeedVisibility field to UpdateStreamConfig with three modes:
- public: full feed with download URLs (default)
- no-download: version info visible but download URLs stripped
- hidden: empty feed returned without a valid license key

The "no-download" mode is the key commercial pattern — customers
see updates exist (motivating purchase/renewal) but cannot download
without a valid key. Joomla shows "update available" in admin.

Applied consistently across all update feed endpoints (Joomla XML,
Dolibarr JSON, WordPress JSON) via the shared validateUpdateKey()
which now returns a stripDownloads flag.

Also: when licensing is enabled, the release listing page requires
login. Anonymous users are redirected to the login page. This
prevents browsing release notes and download links without auth.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 06:38:09 -05:00
Jonathan Miller 448b7d3ab0 feat(licenses): archive, search, download gating, changelog XML, and expanded permissions
Migration v340: sync all missing columns (key_raw, payment_ref,
last_heartbeat_unix, is_archived, licensing_enabled, download_gating,
support_url, and all extension metadata fields).

Package archiving (#384): add IsArchived field with archive/unarchive
handlers and collapsible "Archived Packages" section in templates.
Existing keys from archived packages continue to work.

Expanded delete permissions (#385): org owners and site admins can
permanently delete packages and keys (previously site admin only).

Search (#392): server-side search across key_prefix, key_raw,
licensee_name, licensee_email, domain_restriction, and payment_ref
via ?q= query parameter on both repo and org licenses pages.

Sortable tables (#390): Fomantic UI sortable class on keys table
with new Domain column showing DomainRestriction per key.

Download gating (#347): three modes — none, prerelease-only, and
all downloads. CheckDownloadGating() intercepts both release
attachment and git archive download handlers.

Support URL (#393): configurable SupportURL field on
UpdateStreamConfig for wiki or external site links.

Changelog XML (#343): ServeChangelogXML endpoint at /changelog.xml
generates Joomla-compatible changelog from release notes. Parses
Keep-a-Changelog markdown sections into <security>, <fix>,
<addition>, <change>, <remove>, <note> XML elements.

API renew (#387): POST /license-keys/{id}/renew endpoint extends
key expiration by package duration.

Closes #384, #385, #386, #387, #389, #390, #392, #393
Refs #343, #346, #347

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-01 04:45:20 -05:00
Jonathan Miller d30e7d7a5a feat(updates): extension metadata settings for update feed generation
Branch Policy Check / Verify merge target (pull_request) Has been cancelled
Universal: PR Check / Branch Policy (pull_request) Has been cancelled
Universal: PR Check / Validate PR (pull_request) Has been cancelled
Branch Cleanup / Delete merged branch (pull_request) Has been cancelled
PR RC Release / Build RC Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
- Add configurable fields: element name, display name, description,
  extension type, maintainer, maintainer URL, info URL, target version,
  PHP minimum
- Add platform dropdown: joomla, dolibarr, wordpress, prestashop,
  drupal, composer, both
- Update Joomla XML generator to use metadata from config (falls back
  to repo-derived values when not set)
- Add GetEffectiveConfig() for resolving repo → org → nil config chain
- Add locale keys for all new settings fields

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 10:58:45 -05:00
Jonathan Miller ed79a48119 feat(licenses): UI/UX cleanup, permissions, renew, auto-domain, custom keys
- Replace confirm() with Gitea modal system (link-action + data-modal-confirm)
- Add confirmation modal to revoke key action
- Fix clipboard copy to use data-clipboard-target with tooltip feedback
- Localize all hardcoded English strings (feed labels, "unlimited", "Master")
- Improve key creation flash with security-focused message + copy button
- Add count badge to org licenses nav tab
- Add icon to org settings navbar for update streams
- Add help text to "Active" checkboxes explaining deactivation impact
- Fix empty state message to reference UI creation (not just API)
- Compact tables for denser license data display
- Add orange "Master" label to master package rows
- Conditional feed buttons on release page (only when licensing enabled)
- Add TypeLicenses unit type with Read/Write/Admin team permissions
- Route-level permission enforcement via RequireUnitReader/Writer
- Add "Renew" action for license keys (extends by package duration)
- Auto-associate domain on first heartbeat (lock-on-first-use)
- Enforce max_sites limit during domain auto-association
- Allow site admins and org owners to set custom license key values

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 08:54:29 -05:00
Jonathan Miller b77da17f38 feat(licenses): implement full commercial license management system
Add key editing, domain enforcement, purchase webhooks, public
validation API, channels multiselect, Joomla downloadkey element,
licensing feature toggle, unified update system, release tag
enforcement, heartbeat tracking, and improved settings UX.

Phase 1: Full key display with AbsoluteShort dates, master package
protection (hide edit/delete in UI, reject in handlers).

Phase 2: Key edit page with template, handlers, and routes for both
repo and org levels. Master keys redirect away.

Phase 3: Domain restriction checking against CSV allowlist,
MaxSites enforcement via CountUniqueDomainsByKey and
IsDomainKnownForKey, dlid query param support for Joomla.

Phase 4: Purchase webhook (POST /license-keys/purchase) with
PaymentRef idempotency. Public validation endpoint
(POST /license-keys/validate) outside auth middleware.
PATCH /license-keys/{id} for API key editing.

Phase 5: Channels multiselect using org UpdateStreamConfig streams
rendered as checkboxes, stored as JSON arrays.

Additional: downloadkey XML element, LicensingEnabled toggle on
UpdateStreamConfig, Dolibarr endpoint unified with key validation,
release tag suffix enforcement, LastHeartbeatUnix field with
TouchHeartbeat, and cleaned-up settings pages.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 01:31:51 -05:00
Jonathan Miller d75e648970 feat(org): add Update Streams settings page in org settings
Branch Policy Check / Verify merge target (pull_request) Has been cancelled
Universal: PR Check / Branch Policy (pull_request) Has been cancelled
PR RC Release / Build RC Release (pull_request) Has been cancelled
Universal: PR Check / Validate PR (pull_request) Has been cancelled
Branch Cleanup / Delete merged branch (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Add "Licenses & Update Streams" tab to org settings sidebar with:
- Stream mode: Joomla standard or Custom
- Active streams table showing name, suffix, description
- Custom streams JSON editor
- Saves org-level defaults that repos inherit

Ref #265

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 23:09:07 -05:00
Jonathan Miller 1032ae4268 feat: organization-level 2FA requirement for members (#208)
Branch Policy Check / Verify merge target (pull_request) Has been cancelled
PR RC Release / Build RC Release (pull_request) Has been cancelled
Adds a Require2FA toggle to organization settings. When enabled,
org members without 2FA are redirected to the security settings
page with a warning flash message.

Changes:
- New Require2FA field on User model (migration v333)
- Org settings UI checkbox with shield-lock icon
- Check2FARequirement middleware on member-required org routes
- UpdateOptions extended with Require2FA field

Closes #208

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-26 13:11:15 -05:00
Copilot b093c2c43c refactor(templates): remove ctxData from tmpl files, use ctx.RootData instead (#37567)
Sub-templates have direct access to `ctx.RootData` (the root data map),
so there is no need for callers to explicitly pass it as `ctxData` via `dict`.

Also fix #37569 by the way

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: wxiaoguang <2114189+wxiaoguang@users.noreply.github.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-05-06 18:21:48 +00:00
wxiaoguang 134e86c78c Refactor "flex-list" to "flex-divided-list" (#37505)
Purpose:

1. Make the whole code base have unified "item" layout
2. Clarify our "list" styles: "flex-relaxed-list", "flex-divided-list"
3. Prepare to replace legacy "ui relaxed list"
* https://github.com/go-gitea/gitea/pull/37445#discussion_r3144458865
4. Prepare for refactoring the "pull merge box", it needs the
"flex-divided-list"
    * related to "Refactor pull request view (*)" like #37451
5. Fix legacy abuses of "flex-list", e.g.: repo home sidebar
2026-05-02 16:10:52 +00:00
Excellencedev 45809c8f54 feat: Add configurable permissions for Actions automatic tokens (#36173)
## Overview

This PR introduces granular permission controls for Gitea Actions tokens
(`GITEA_TOKEN`), aligning Gitea's security model with GitHub Actions
standards while maintaining compatibility with Gitea's unique repository
unit system.

It addresses the need for finer access control by allowing
administrators and repository owners to define default token
permissions, set maximum permission ceilings, and control
cross-repository access within organizations.

## Key Features

### 1. Granular Token Permissions

- **Standard Keyword Support**: Implements support for the
`permissions:` keyword in workflow and job YAML files (e.g., `contents:
read`, `issues: write`).
- **Permission Modes**:
- **Permissive**: Default write access for most units (backwards
compatible).
- **Restricted**: Default read-only access for `contents` and
`packages`, with no access to other units.
- ~~**Custom**: Allows defining specific default levels for each unit
type (Code, Issues, PRs, Packages, etc.).~~**EDIT removed UI was
confusing**
- **Clamping Logic**: Workflow-defined permissions are automatically
"clamped" by repository or organization-level maximum settings.
Workflows cannot escalate their own permissions beyond these limits.

### 2. Organization & Repository Settings

- **Settings UI**: Added new settings pages at both Organization and
Repository levels to manage Actions token defaults and maximums.
- **Inheritance**: Repositories can be configured to "Follow
organization-level configuration," simplifying management across large
organizations.
- **Cross-Repository Access**: Added a policy to control whether Actions
workflows can access other repositories or packages within the same
organization. This can be set to "None," "All," or restricted to a
"Selected" list of repositories.

### 3. Security Hardening

- **Fork Pull Request Protection**: Tokens for workflows triggered by
pull requests from forks are strictly enforced as read-only, regardless
of repository settings.
- ~~**Package Access**: Actions tokens can now only access packages
explicitly linked to a repository, with cross-repo access governed by
the organization's security policy.~~ **EDIT removed
https://github.com/go-gitea/gitea/pull/36173#issuecomment-3873675346**
- **Git Hook Integration**: Propagates Actions Task IDs to git hooks to
ensure that pushes performed by Actions tokens respect the specific
permissions granted at runtime.

### 4. Technical Implementation

- **Permission Persistence**: Parsed permissions are calculated at job
creation and stored in the `action_run_job` table. This ensures the
token's authority is deterministic throughout the job's lifecycle.
- **Parsing Priority**: Implemented a priority system in the YAML parser
where the broad `contents` scope is applied first, allowing granular
scopes like `code` or `releases` to override it for precise control.
- **Re-runs**: Permissions are re-evaluated during a job re-run to
incorporate any changes made to repository settings in the interim.

### How to Test

1. **Unit Tests**: Run `go test ./services/actions/...` and `go test
./models/repo/...` to verify parsing logic and permission clamping.
2. **Integration Tests**: Comprehensive tests have been added to
`tests/integration/actions_job_token_test.go` covering:
   - Permissive vs. Restricted mode behavior.
   - YAML `permissions:` keyword evaluation.
   - Organization cross-repo access policies.
- Resource access (Git, API, and Packages) under various permission
configs.
3. **Manual Verification**: 
   - Navigate to **Site/Org/Repo Settings -> Actions -> General**.
- Change "Default Token Permissions" and verify that newly triggered
workflows reflect these changes in their `GITEA_TOKEN` capabilities.
- Attempt a cross-repo API call from an Action and verify the Org policy
is enforced.

## Documentation

Added a PR in gitea's docs for this :
https://gitea.com/gitea/docs/pulls/318

## UI:

<img width="1366" height="619" alt="Screenshot 2026-01-24 174112"
src="https://github.com/user-attachments/assets/bfa29c9a-4ea5-4346-9410-16d491ef3d44"
/>

<img width="1360" height="621" alt="Screenshot 2026-01-24 174048"
src="https://github.com/user-attachments/assets/d5ec46c8-9a13-4874-a6a4-fb379936cef5"
/>

/fixes #24635
/claim #24635

---------

Signed-off-by: Excellencedev <ademiluyisuccessandexcellence@gmail.com>
Signed-off-by: ChristopherHX <christopher.homberger@web.de>
Signed-off-by: silverwind <me@silverwind.io>
Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: ChristopherHX <christopher.homberger@web.de>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Zettat123 <zettat123@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-03-21 15:39:47 -07:00
xiaox 3b250ba04e refactor: replace legacy tw-flex utility classes with flex-text-block/inline (#36778)
## Summary

Replace combinations of `tw-flex tw-items-center` (with optional
`tw-gap-*`) with semantic `flex-text-block` or `flex-text-inline`
classes across 15 template files.

This follows the refactoring direction outlined in #35015 ("Refactor
legacy `tw-flex tw-items-center tw-gap-xx` to `flex-text-block` or
`flex-text-inline`").

## Changes

### Replacement rules applied:
- `tw-flex tw-items-center tw-gap-2` → `flex-text-block` (both have
`gap: 0.5rem`)
- `tw-flex tw-items-center tw-gap-1` → `flex-text-inline` (both have
`gap: 0.25rem`)
- `tw-flex tw-items-center` (no explicit gap) → `flex-text-block` where
the element is block-level and children benefit from the default gap
- `tw-flex tw-items-center` (inline context, e.g. `<a>`, `<span>`) →
`flex-text-inline`

### Files modified (15):
- `templates/admin/config.tmpl` — config page dt elements
- `templates/admin/repo/unadopted.tmpl` — unadopted repo list items
- `templates/base/head_navbar.tmpl` — active stopwatch popup
- `templates/org/header.tmpl` — org header action buttons
- `templates/org/home.tmpl` — member/team count links
- `templates/org/settings/labels.tmpl` — labels page header
- `templates/repo/branch/list.tmpl` — branch list header
- `templates/repo/commits_table.tmpl` — commits table header
- `templates/repo/diff/box.tmpl` — diff detail box
- `templates/repo/diff/new_review.tmpl` — review form header
- `templates/repo/issue/card.tmpl` — issue card unpin button
- `templates/repo/issue/view_content/attachments.tmpl` — attachment file
size
- `templates/repo/migrate/migrate.tmpl` — migration service cards
- `templates/shared/user/org_profile_avatar.tmpl` — org profile header
- `templates/webhook/new.tmpl` — webhook type dropdown text

### What was NOT changed:
- Elements with `tw-justify-between` or `tw-justify-center` (these need
additional classes)
- Elements whose children use explicit margins (`tw-mr-*`, `tw-ml-*`)
that would conflict with the gap from flex-text classes
- Fomantic UI form elements with special layout requirements

## Notes
- This PR was created with AI assistance (Claude). All changes were
reviewed individually to ensure semantic correctness and zero unintended
visual changes.
- No functional changes — purely CSS class refactoring.

Closes: part of #35015

Signed-off-by: xiaox315 <xiaox315@users.noreply.github.com>
Co-authored-by: xiaox315 <xiaox315@users.noreply.github.com>
2026-02-28 14:03:25 +01:00
silverwind 6e7991316c Refactor text utility classes to Tailwind CSS (#36703)
Replace Fomantic/custom CSS text utility classes with their Tailwind
equivalents:

- `.text.<color>` compound classes → `tw-text-<color>` classes
- `.text.small` (`font-size: 0.75em`) → `tw-text-xs` (11px)
- `.text.truncate` (`overflow-x: hidden; text-overflow: ellipsis;
white-space: nowrap; display: inline-block`) → `tw-inline-block
tw-truncate`

Remove the now-unused CSS rules from `base.css` and `dashboard.css`.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 22:56:33 +00:00
silverwind 42d294941c Replace CSRF cookie with CrossOriginProtection (#36183)
Removes the CSRF cookie in favor of
[`CrossOriginProtection`](https://pkg.go.dev/net/http#CrossOriginProtection)
which relies purely on HTTP headers.

Fixes: https://github.com/go-gitea/gitea/issues/11188
Fixes: https://github.com/go-gitea/gitea/issues/30333
Helps: https://github.com/go-gitea/gitea/issues/35107

TODOs:

- [x] Fix tests
- [ ] Ideally add tests to validates the protection

---------

Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-12-25 12:33:34 +02:00
Lunny Xiao c0f24bd803 Move organization's visibility change to danger zone. (#34814)
<img width="1185" alt="image"
src="https://github.com/user-attachments/assets/d48c4db2-df7c-43b3-986c-62e042190a51"
/>

<img width="829" alt="image"
src="https://github.com/user-attachments/assets/772b8a14-6837-41f2-9d78-9f0489ef1c7d"
/>

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-08-20 20:57:42 -07:00
wxiaoguang e0745eb14d Refactor webhook and fix feishu/lark secret (#34961) 2025-07-06 06:04:08 +00:00
Lunny Xiao 7de114a332 Rework delete org and rename org UI (#34762)
# What's the problem of the original implementation

Renaming organization will mix with organization's information change
make the operation difficult to keep consistent.

This PR created a danger zone like what's repository setting. It also
moved organization's `rename` and `delete` operations to this zone. The
original updating repository will not change the name any more.

This is also a step to extract the `updaterepository` function
completely.

Before:


![image](https://github.com/user-attachments/assets/d097dfdf-07be-4d79-8fcf-e78822515575)

![image](https://github.com/user-attachments/assets/42ee832c-cb44-41ec-9fe3-92a1c94747d2)

After:


![image](https://github.com/user-attachments/assets/f7700ed7-f104-4302-a924-09e118f24be3)

![image](https://github.com/user-attachments/assets/4c49952a-578e-4d14-bd01-4a68c9e02412)

![image](https://github.com/user-attachments/assets/814829d3-00fe-4e87-ae05-625c129170d2)

![image](https://github.com/user-attachments/assets/b067b263-c909-4b48-b23c-73481c32d350)

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-06-21 18:21:48 +00:00
wxiaoguang f63822fe64 Fix autofocus behavior (#34397)
The "autofocus" was abused or misbehaved:

1. When users visit a page but they are not going to change a field,
then the field shouldn't get "autofocus"
* the "auth" / "user" page: in most cases, users do not want to change
the names
    * see also the GitHub's "settings" page behavior.
2. There shouldn't be duplicate "autofocus" inputs in most cases, only
the first one focuses
3. When a panel is shown, the "autofocus" should get focus
    * "add ssh key" panel

This PR fixes all these problems and by the way remove duplicate
"isElemHidden" function.
2025-05-08 18:26:18 +00:00
Kerwin Bryant 40426addfa Add cropping support when modifying the user/org/repo avatar (#33498)
Fixed #33321

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-02-06 21:07:44 +08:00
wxiaoguang 96d3a03a08 Refactor LabelEdit (#32752)
And fix a regression:
https://github.com/go-gitea/gitea/pull/30053#discussion_r1874405470

Major changes:

* rewrite without jquery
* remove the "delete modal", using "link-action" is good enough
* merge "new modal" and "edit modal"
2024-12-08 02:35:28 +00:00
wxiaoguang c9e582c6b6 Refactor markdown editor and use it for milestone description editor (#32688)
Refactor markdown editor to clarify its "preview" behavior and remove
jQuery code.

Close #15045

---------

Co-authored-by: silverwind <me@silverwind.io>
2024-12-04 02:11:34 +00:00
silverwind ec3d467f15 Migrate gt-hidden to tw-hidden (#30046)
We have to define this one in helpers.css because tailwind only
generates a single class but certain things rely on this being
double-class. Command ran:

```sh
perl -p -i -e 's#gt-hidden#tw-hidden#g' web_src/js/**/* templates/**/* models/**/* web_src/css/**/*

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2024-03-24 18:23:38 +00:00
silverwind 04f9ad0568 Fix incorrect tailwind migration (#30007)
Fixes https://github.com/go-gitea/gitea/issues/30005. Regression from
https://github.com/go-gitea/gitea/pull/29945.

There was only once instance of `tw-content-center` before that PR, so I
just ran below command and reverted that one instance.

```sh
perl -p -i -e 's#tw-content-center#tw-items-center#g' web_src/js/**/* templates/**/* models/**/* tests/**/*
```
2024-03-22 20:51:29 +01:00
silverwind f88ad5424f Replace 10 more gt- classes with tw- (#29945)
Likely the biggest change of the tailwind refactors. Only thing of note
is that `tw-flex-1` resolves to `flex: 1 1 0%` while our `gt-f1` was
`flex: 1 1 0`, I don't think it will make any difference. Commands I've
ran:

```sh
perl -p -i -e 's#gt-vm#tw-align-middle#g' web_src/js/**/* templates/**/* models/**/*
perl -p -i -e 's#gt-fw#tw-flex-wrap#g' web_src/js/**/* templates/**/* models/**/*
perl -p -i -e 's#gt-f1#tw-flex-1#g' web_src/js/**/* templates/**/* models/**/*
perl -p -i -e 's#gt-fc#tw-flex-col#g' web_src/js/**/* templates/**/* models/**/*
perl -p -i -e 's#gt-sb#tw-justify-between#g' web_src/js/**/* templates/**/* models/**/*
perl -p -i -e 's#gt-je#tw-justify-end#g' web_src/js/**/* templates/**/* models/**/*
perl -p -i -e 's#gt-jc#tw-justify-center#g' web_src/js/**/* templates/**/* models/**/*
perl -p -i -e 's#gt-ac#tw-content-center#g' web_src/js/**/* templates/**/* models/**/* tests/**/*
perl -p -i -e 's#gt-df#tw-flex#g' web_src/js/**/* templates/**/* models/**/* tests/**/*
perl -p -i -e 's#gt-dib#tw-inline-block#g' web_src/js/**/* templates/**/* models/**/* tests/**/*

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2024-03-22 13:45:10 +00:00
KN4CK3R c337ff0ec7 Add user blocking (#29028)
Fixes #17453

This PR adds the abbility to block a user from a personal account or
organization to restrict how the blocked user can interact with the
blocker. The docs explain what's the consequence of blocking a user.

Screenshots:


![grafik](https://github.com/go-gitea/gitea/assets/1666336/4ed884f3-e06a-4862-afd3-3b8aa2488dc6)


![grafik](https://github.com/go-gitea/gitea/assets/1666336/ae6d4981-f252-4f50-a429-04f0f9f1cdf1)


![grafik](https://github.com/go-gitea/gitea/assets/1666336/ca153599-5b0f-4b4a-90fe-18bdfd6f0b6b)

---------

Co-authored-by: Lauris BH <lauris@nix.lv>
2024-03-04 08:16:03 +00:00
wxiaoguang c9d0e63c20 Remove unnecessary "Str2html" modifier from templates (#29319)
Follow #29165
2024-02-22 18:05:47 +00:00
silverwind cbc0b7307d Use flex-container for repo and org settings (#27418)
Same as https://github.com/go-gitea/gitea/pull/26046 but for repo and
org settings pages, reducing the margins between the boxes:

<img width="1247" alt="Screenshot 2023-10-03 at 23 25 19"
src="https://github.com/go-gitea/gitea/assets/115237/4e68ad5e-5fdc-4466-aefb-ec71bf411d45">
<img width="1255" alt="Screenshot 2023-10-03 at 23 27 12"
src="https://github.com/go-gitea/gitea/assets/115237/9068369b-a75d-401e-8b8d-3bd4bbe097dc">

Co-authored-by: Giteabot <teabot@gitea.io>
2023-10-04 08:47:54 +02:00
wxiaoguang 93bd4351bf Fix more "locale" usages (#27259) 2023-09-25 20:42:40 +08:00
delvh 7960ba7e2b Always use ctx.Locale.Tr inside templates (#27231) 2023-09-25 08:56:50 +00:00
silverwind 8099238618 Change green buttons to primary color (#27099)
I think it's better if the primary actions have primary color instead of
green which fits better into the overall single-color UI design. This PR
currently replaces every green button with primary:

<img width="141" alt="Screenshot 2023-09-16 at 14 07 59"
src="https://github.com/go-gitea/gitea/assets/115237/843c1e50-4fb2-4ec6-84ba-0efb9472dcbe">
<img width="161" alt="Screenshot 2023-09-16 at 14 07 51"
src="https://github.com/go-gitea/gitea/assets/115237/9442195a-a3b2-4a42-b262-8377d6f5c0d1">

Modal actions now use uncolored/primary instead of previous green/red
colors. I also removed the box-shadow on all basic buttons:

<img width="259" alt="Screenshot 2023-09-16 at 14 16 39"
src="https://github.com/go-gitea/gitea/assets/115237/5beea529-127a-44b0-8d4c-afa7b034a490">
<img width="261" alt="Screenshot 2023-09-16 at 14 17 42"
src="https://github.com/go-gitea/gitea/assets/115237/4757f7b2-4d46-49bc-a797-38bb28437b88">

The change currently includes the "Merge PR" button, for which we might
want to make an exception to match the icon color there:

<img width="442" alt="Screenshot 2023-09-16 at 14 33 53"
src="https://github.com/go-gitea/gitea/assets/115237/993ac1a5-c94d-4895-b76c-0d872181a70b">
2023-09-18 22:05:31 +00:00
Kerwin Bryant 9b0743ae33 Extract common code to new template (#26933)
Same as #26903
2023-09-06 10:11:06 +00:00
Kerwin Bryant 65588b732c Extract common code to new template (#26903)
I noticed that the code of several new webhook pages is highly
repetitive, so I pulled out the common parts to a new template, unified
reference, unified maintenance

---------

Co-authored-by: KN4CK3R <admin@oldschoolhack.me>
2023-09-05 12:00:28 +00:00
wxiaoguang 19a1e1b20e Remove polluted .ui.right (#26825)
Each change is tested manually line by line. There are too many changes
so I can't share dozens of screenshots.

In short:

1. `ui right` could be still used in `ui top attached header`, because
there is a special case.
2. A lot of `ui right` are just no-op, so they can be removed safely.
3. Some of the `ui right` should be replaced by `gt-float-right` (to
avoid breaking, leave them to the future).
4. A few of the `ui right` could be rewritten by flex.
2023-08-31 02:29:59 +00:00
wxiaoguang 4fdb09de58 Fix incorrect "tabindex" attributes (#26733)
Fix #26731

Almost all "tabindex" in code are incorrect.

1. All "input/button" by default are focusable, so no need to use "tabindex=0"
2. All "div/span" by default are not focusable, so no need to use "tabindex=-1"
3. All "dropdown" are focusable by framework, so no need to use "tabindex"
4. Some tabindex values are incorrect (eg: `new_form.tmpl`), so remove them

Co-authored-by: Giteabot <teabot@gitea.io>
2023-08-26 10:44:00 +08:00
wxiaoguang e8b990999f Make "link-action" backend code respond correct JSON content (#26680)
Otherwise the `link-action` JS code couldn't parse the response.

Co-authored-by: Giteabot <teabot@gitea.io>
2023-08-23 17:36:57 +08:00
silverwind 72363be7ca Use shared template for webhook icons (#26242)
Fixes: https://github.com/go-gitea/gitea/issues/26241
2023-07-31 08:00:52 +00:00