License Management Add-on for Larapen
Latest: v1.0.32 6 November 2026 22 releases
Back to product
    • Added: the 'Block requests without a license key' option (Settings → .htaccess Blocklist → Required request parameters), off by default; verify / activate / deactivate and legacy calls that send no key are rejected with the same HTTP 403 as a banned request and are not logged
    • Added: the 'Block requests without a domain' option, off by default; calls that send no domain are rejected the same way (clients identifying by 'machine_id' only are rejected too, so leave it off for desktop software)
    • Updated: while the .htaccess blocklist is enabled, both rules are also written into the Apache rules (GET requests) or baked into the 'public/licenses.php' precheck gatekeeper, so those calls never reach Laravel; the block is now written even when nothing is banned
    • Updated: the precheck gatekeeper now reads a license key or domain sent in a JSON body, and uses the configured legacy parameter names instead of hard-coded ones
    • Updated: saving the settings regenerates the blocklist whenever a setting baked into it changes (IP banning, the two new rules, or the oracle-safe ban response), instead of only when IP banning flips
    • Fixed: in the PHP precheck strategy, the 'public/licenses.php' gatekeeper returned a 404 for every allowed API call on Apache setups where REDIRECT_URL carries the rewrite target instead of the original path: the request URI is now only restored when it really points at the gatekeeper
    • Fixed: a license key activated on 'toto.com' was refused on 'www.toto.com' (and vice versa) once its activation limit was reached: both spellings now resolve to the same activation. Domains are also compared without regard to case, scheme, port or path
    • Added: the 'Treat www. as the same domain' option (Settings → Domains), enabled by default; disable it to count the www alias as a separate site
    • Added: the 'Allow subdomains of activated domains' option (Settings → Domains), disabled by default; when enabled, every host of one domain ('toto.com', 'fr.toto.com', 'de.toto.com') shares a single activation, whichever host was activated first
    • Updated: banned domains follow the same rules, so banning 'toto.com' also rejects 'www.toto.com' (and its subdomains when that option is on)
    • Updated: existing activations and banned domains are normalized once during this update; a key that already held both 'toto.com' and 'www.toto.com' keeps the oldest activation and the duplicate is deactivated
    • The License Products picker (store filter, keyword search, slug / SKU / version on every row) is now what links an Envato item or a Gumroad product to the license products it sells, inside a modal on those lists
    • A license product can be created from the marketplace listing without leaving that modal: the bridge endpoints now return the product they created so it can be selected straight away
    • Marketplace admins (envato.links.edit / gumroad.links.edit) may search the license products catalogue
    • Removed the per-row "Create / Update license product" buttons of the Envato and Gumroad admins, replaced by the modal
    • The products list carries a link control per kind of gated entity (support department, knowledge base collections, forum categories), each opening its own modal
    • New "IP Banning" option (Settings → Blocklist), disabled by default: while it is off no request is blocked because of its source IP and the Banned IPs tab is hidden, and existing IP bans are kept in the database and enforced again as soon as it is switched back on
    • Saving the licenses settings now reconciles the generated .htaccess / precheck blocklist with those settings: it is regenerated when the IP banning switch flips, and a blocklist still applied after the blocklist option was turned off is removed (rules generated earlier kept rejecting banned IPs before PHP ran)
    • Before a key is banned automatically for tripping the API rate limit, other add-ons are asked whether it should be spared: the HelpDesk add-on uses this to protect the keys of its top-tier customers
    • Bans an administrator makes by hand are unaffected: only the automatic rate-limit ban consults the new check
    • New command licenses:doctor: audits the links between license products and the stores that sell them (Envato, Gumroad, Shop) and reports wrong-listing links, orphan rows, one listing granting several products, imports never linked, and gated entities closed to a store's customers
    • Findings a human confirms as intentional can be silenced with licenses:doctor --acknowledge; the acknowledgement records the titles it was granted for, so a listing renamed again is reported anew
    • New command licenses:merge-products: folds per-store duplicate license products into a single product carrying every store link, moving keys, gated entities and store links
    • Fixed the forum category target of the licenses link enum, which named a model class that does not exist
    • Fixed a 500 error (Unknown column 'license_product_id') when clicking 'Create license product' on a shop product that occurred when the licenses add-on had been installed before the Shop add-on
    • The shop_products.license_product_id column is now added on upgrade if it is missing, regardless of the order in which the licenses and Shop add-ons were installed
    • The licenses add-on now self-heals this column at boot whenever the Shop add-on is active but the column is absent
    • Consolidated the licenses_activations.is_local column: it is now part of the create-table migration for fresh installs and reconciled by an update migration for existing installs (the standalone alter migration was removed)
    • Shop digital products now expose a 'Create/Update license product' button (products list + edit page) that links the product to a license product (button only shown when the licenses add-on is active)
    • License keys issued for a shop order are now disabled (suspended) automatically when the order is refunded, the payment fails or reverts to unpaid, or the order is cancelled
    • Disabled keys are re-enabled automatically if the order is confirmed (paid/completed) again
    • Added the LicenseKeyDisabledNotification: buyers are emailed their affected key(s) when keys are disabled due to an order change (new notification type 'licenses_license_key_disabled')
    • Added translation keys (en, fr, ar): license_disabled_*, shop_link.*, notification_type_license_key_disabled*
    • Added slug_aliases JSON column on licenses_products to expose alternate identifiers (slug, sku, item_id, or any alias) accepted by the API verify endpoint
    • Added UniqueProductSlugAliases validation rule enforcing global uniqueness across slug + every product's slug_aliases (no two products can share an identifier)
    • Extended UniqueProductSlug rule to also reject collisions with other products' slug_aliases
    • Added LicenseProductService::findByAnySlug() (cached): used by resolveProductFromProviderData so an Envato verify no longer creates a duplicate product when the primary slug was renamed but the original slug is kept as an alias
    • Updated LicenseKeyProviderService::productMatches() to accept slug, slug_aliases, sku, or metadata->item_id
    • Renamed verify() / findOrCreateFromProvider() parameter from $productSlug to $productIdentifier to reflect the broader matching semantics
    • Locked the slug field as read-only in the admin product edit modal when the product is linked to an Envato item, with an inline hint suggesting to add a slug alias instead; UpdateLicenseProductRequest also strips any submitted slug for Envato-linked products to defend against hand-crafted POSTs
    • Added LicenseProduct::isLinkedToEnvato() helper (metadata.source=envato OR envato_id OR item_id)
    • Added slug aliases input to product create/edit modals (comma-separated; trimmed, lowercased, deduped, primary slug stripped before validation) and chips display in the product list table
    • Added new translation keys (en + fr): slug_alias, slug_aliases, slug_aliases_help, slug_locked_envato_help, slug_alias_taken, slug_alias_duplicate_in_list
    • Added Addons\Licenses\Http\Controllers\Admin\LicenseCustomerController with index (search, product, status, provider filters) and show actions; index returns a partial for AJAX refreshes
    • Added admin routes admin.licenses.customers.index and admin.licenses.customers.show
    • Added admin views admin/customers/index.blade.php, _table.blade.php, and show.blade.php
    • Added Customers entry to the Licenses admin sub-menu
    • Added new permission licenses.customers.view (granted to the admin role on update)
    • Added a 'View Customer' button to the helpdesk ticket sidebar 'Customer Licenses' card footer (mirrors the Envato pattern)
    • Added licenses_entity_links polymorphic table linking license products to helpdesk departments, KB collections, and forum categories
    • Added Addons\Licenses\Enums\LinkableType enum (HelpdeskDepartment, HelpdeskKbCollection, ForumCategory)
    • Added Addons\Licenses\Services\LicensesAccessService with getUserLicensedProductIds(), getAccessibleEntityIds(), syncLinkedLicenseProducts(), and isRequired(): drop-in replacement for EnvatoPurchaseValidator semantics
    • Renamed settings: envato_helpdesk_require_purchase → licenses_helpdesk_require_purchase, envato_kb_restrict_by_purchase → licenses_kb_restrict_by_purchase, envato_forum_require_purchase → licenses_forum_require_purchase
    • Backfill: created LicenseKey rows from envato_user_purchases so users with verified purchases retain access after the cutover