Coder Social home page Coder Social logo

laravel-ready / license-server Goto Github PK

View Code? Open in Web Editor NEW
81.0 4.0 18.0 48 KB

Ready to use License Server package for Laravel. Add a licensing system to your products or services.

License: MIT License

PHP 100.00%
license license-management license-server laravel license-system

license-server's Introduction

License Server

EgoistDeveloper Laravel License Server

Stable Version Unstable Version Total Downloads License

๐Ÿ“‚ About

License Server package, which is a Laravel package that allows you to manage your Laravel applications license. You can use it with any product or service. License Server comes with the agnostic license management system, which allows you to manage your licenses in a simple and easy way. Just add license relation to any product model then you can work in your logic.

This package requires license-connector package. License Connector is client implementation for License Server. Package for the client makes a request to License Server and gets a response.

๐Ÿ“‹ Requirements

PHP

This package requires PHP 8.0 or higher. Also these extesnions are required:

If the above extensions already installed, you can enable them with php.ini.

Laravel

This package requires Laravel 8.x or higher. Other versions are ignored.

๐Ÿ“ฆ Installation (for Host App)

Get via composer

composer require laravel-ready/license-server

Publish migrations and migrate

# publish migrations
php artisan vendor:publish --tag=license-server-migrations

# apply migrations
php artisan migrate --path=/database/migrations/laravel-ready/license-server

Configs are very important. You can find them in license-server.php file. You should read all configs and configure for your needs.

# publish configs
php artisan vendor:publish --tag=license-server-configs

๐Ÿ—๏ธ Model Relations

Every license must-have product, because we need to know what it is licensed for. The client application will send this information to the License Server. Then we can check if the license is valid for given the product.

Product model can be any model that you want to be licensed. Add Licensable trait to your product model.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;

use LaravelReady\LicenseServer\Traits\Licensable;

class Product extends Model
{
    use HasFactory, Licensable;

    protected $table = 'products';

    protected $fillable = [
        'name',
        'description',
        'price',
        'image',
        ...
    ];

    ...
}

๐Ÿ“Œ Service Methods

Add in your namespace list:

use LaravelReady\LicenseServer\Services\LicenseService;

and product model

use App\Models\Product;

addLicense

First, we need to know licensing models. This package supports two types of licensing models: to Domain and to User. Both of them are valid. If you want to add license to domain, you must pass domain parameter. If you want to add license to user, you must pass userId parameter. Also, when you pass both of them, you will get domain license.

// get licensable product
$product = Product::find(1);
$user = User::find(1);

// add license to domain
$license = LicenseService::addLicense($product, 'example.com', $user->id);

// add license to user
$license = LicenseService::addLicense($product, null, $user->id);

// with expiration in days (see configs for defaults)
$license = LicenseService::addLicense($product, null, $user->id, 999);

// with lifetime license (see configs for defaults)
$license = LicenseService::addLicense($product, null, $user->id, null, true);

// with trial license (see configs for defaults)
$license = LicenseService::addLicense($product, null, $user->id, null, false, true);
  • If you provide domain, then the license will be added to the domain. If you don't provide domain, then the license will be added to the user (in this case user id is required.).
  • Other parameters are optional and do not forget to configure configs.
  • This method returns LaravelReady\LicenseServer\Models\License model.
  • All license keys are in UUID format.

getLicenseBy*

  • getLicenseByKey: get license by license key.
    • LicenseService::getLicenseByKey(string $licenseKey)
  • getLicenseByUserId: get license by user id and license key.
    • LicenseService::getLicenseByUserId(int $userId, string $licenseKey = null)
  • getLicenseByDomain: get license by domain and license key.
    • LicenseService::getLicenseByDomain(string $domain, string $licenseKey = null)

checkLicenseStatus

// license key in uuid format
$licenseKey = "46fad906-bc51-435f-9929-db46cb4baf13";

// check license status
$licenseStatus = LicenseService::checkLicenseStatus($licenseKey);

Returns "active", "inactive", "suspended", "expired", "invalid-license-key" and "no-license-found".

setLicenseStatus

// license key in uuid format
$licenseKey = "46fad906-bc51-435f-9929-db46cb4baf13";

// check license status
$licenseStatus = LicenseService::setLicenseStatus($licenseKey, "suspended");

You can only set active, inactive, suspended status.

๐Ÿ› ๏ธ Custom Controller

If you want to use own license validation controller you can integrate it easily.

Click to see the example!
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Event;

use LaravelReady\LicenseServer\Models\License;
use LaravelReady\LicenseServer\Events\LicenseChecked;

class LicenseController extends Controller
{
    /**
     * Custom license validation
     *
     * @param Request $request
     * @param License $license
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function licenseValidate(Request $request, License $license)
    {
        // this controller is works under 'auth:sanctum' and 'ls-license-guard' middleware
        // in this case 'auth()->user()' will be is our license

        $_license = $license->select(
            'domain',
            'license_key',
            'status',
            'expiration_date',
            'is_trial',
            'is_lifetime'
        )->where([
            ['id', '=', auth()->user()->id],
            ['is_trial', '!=', true]
        ])->first();

        $data = $request->input();

        // event will be fired after license is checked
        // this part depends to your logic, you can remove it or change it
        Event::dispatch(new LicenseChecked($_license, $data));

        $_license->appent_some_data = 'some data and date now -> ' . now();

        return $_license;
    }
}

Then you need to register this custom controller in your config/license-server.php file.

Click to see the example!
/**
 * Custom controllers for License Server
 */
'controllers' => [
    /**
     * License validation controller
     *
     * You can use this controller to handle license validating
     *
     * See the documentation for more information.
     *
     */
    'license_validation' => [
        App\Http\Controllers\LicenseController::class,
        'licenseValidate'
    ]
]

๐Ÿชข Events

๐Ÿชก LicenseChecked Event

You can send custom data with connector and on the license server-side, you can catch this custom data. First you need to create a listener for this event.

php artisan make:listener LicenseCheckedListener --event=LicenseChecked

Add class LicenseChecked with LaravelReady\LicenseServer\Events\LicenseChecked namespace. You can retrieve custom data from event.

<?php

namespace App\Listeners;

use LaravelReady\LicenseServer\Events\LicenseChecked;

class LicenseCheckedListener
{
    public function __construct()
    {
        //
    }

    public function handle(LicenseChecked $event)
    {
        // $event->license,
        // $event->data,
    }
}

Finally, you need to register this listener in your config/license-server.php file.

Click to see the example!
/**
    * Event listeners for License Server
    */
'event_listeners' => [
    /**
        * License checked event listener
        *
        * You can use this event to do something when a license is checked.
        * Also you can handle custom data with this listener.
        *
        * See the documentation for more information.
        *
        * Default: null
        */
    'license_checked' => App\Listeners\LicenseCheckedListener::class,
],

Ready to Use API

Ready to use API is included with simple resource methods. API endpoint is /api/license-server/licenses.

Domain Validation

License Server uses a cache to store the public tld list. See tld list at https://data.iana.org/TLD/tlds-alpha-by-domain.txt

The TLD list cache is will be stored at the storage/license-server/iana-tld-list.txt file and do not edit this file.

In development you may use domain like example.test etc. but you won't pass domain validation because the test is not valid tld.

โš ๏ธ Warnings

  • This package is under active development and is not yet stable. There may be some changes in later versions.
  • Don't forget this package just provides management of licenses and product/customer communication.
  • Please don't confuse it with ioncube or similar source code encryption tools.

license-server's People

Contributors

mohammed059 avatar relliv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

license-server's Issues

Error Checking TLD Domain

Error for creating license with domain

I get this error message
TypeError: Pdp\TopLevelDomains::__construct(): Argument #3 ($lastUpdated) must be of type DateTimeImmutable, bool given, called in D:\laragon\www\sekolahdigital\vendor\jeremykendall\php-domain-parser\src\TopLevelDomains.php on line 54 in file D:\laragon\www\sekolahdigital\vendor\jeremykendall\php-domain-parser\src\TopLevelDomains.php on line 25

D:\laragon\www\sekolahdigital\vendor\jeremykendall\php-domain-parser\src\TopLevelDomains.php(54): Pdp\TopLevelDomains->__construct(Array, '2023120300', false)
D:\laragon\www\sekolahdigital\vendor\jeremykendall\php-domain-parser\src\TopLevelDomains.php(42): Pdp\TopLevelDomains::fromString('# Version 20231...')
D:\laragon\www\sekolahdigital\vendor\laravel-ready\license-server\src\Support\DomainSupport.php(34): Pdp\TopLevelDomains::fromPath('D:\laragon\www\...')
D:\laragon\www\sekolahdigital\vendor\laravel-ready\license-server\src\Http\Middleware\DomainGuardMiddleware.php(20): LaravelReady\LicenseServer\Support\DomainSupport::validateDomain('google.com')
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(180): LaravelReady\LicenseServer\Http\Middleware\DomainGuardMiddleware->handle(Object(Illuminate\Http\Request), Object(Closure))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Routing\Middleware\SubstituteBindings.php(50): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(180): Illuminate\Routing\Middleware\SubstituteBindings->handle(Object(Illuminate\Http\Request), Object(Closure))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Routing\Middleware\ThrottleRequests.php(159): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Routing\Middleware\ThrottleRequests.php(90): Illuminate\Routing\Middleware\ThrottleRequests->handleRequest(Object(Illuminate\Http\Request), Object(Closure), Array)
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(180): Illuminate\Routing\Middleware\ThrottleRequests->handle(Object(Illuminate\Http\Request), Object(Closure), '60', '1')
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Routing\Middleware\ThrottleRequests.php(159): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Routing\Middleware\ThrottleRequests.php(125): Illuminate\Routing\Middleware\ThrottleRequests->handleRequest(Object(Illuminate\Http\Request), Object(Closure), Array)
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Routing\Middleware\ThrottleRequests.php(87): Illuminate\Routing\Middleware\ThrottleRequests->handleRequestUsingNamedLimiter(Object(Illuminate\Http\Request), Object(Closure), 'api', Object(Closure))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(180): Illuminate\Routing\Middleware\ThrottleRequests->handle(Object(Illuminate\Http\Request), Object(Closure), 'api')
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(116): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Routing\Router.php(805): Illuminate\Pipeline\Pipeline->then(Object(Closure))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Routing\Router.php(784): Illuminate\Routing\Router->runRouteWithinStack(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Routing\Router.php(748): Illuminate\Routing\Router->runRoute(Object(Illuminate\Http\Request), Object(Illuminate\Routing\Route))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Routing\Router.php(737): Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php(200): Illuminate\Routing\Router->dispatch(Object(Illuminate\Http\Request))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(141): Illuminate\Foundation\Http\Kernel->Illuminate\Foundation\Http{closure}(Object(Illuminate\Http\Request))
D:\laragon\www\sekolahdigital\vendor\barryvdh\laravel-debugbar\src\Middleware\InjectDebugbar.php(66): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(180): Barryvdh\Debugbar\Middleware\InjectDebugbar->handle(Object(Illuminate\Http\Request), Object(Closure))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\TransformsRequest.php(21): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull.php(31): Illuminate\Foundation\Http\Middleware\TransformsRequest->handle(Object(Illuminate\Http\Request), Object(Closure))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(180): Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull->handle(Object(Illuminate\Http\Request), Object(Closure))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\TransformsRequest.php(21): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\TrimStrings.php(40): Illuminate\Foundation\Http\Middleware\TransformsRequest->handle(Object(Illuminate\Http\Request), Object(Closure))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(180): Illuminate\Foundation\Http\Middleware\TrimStrings->handle(Object(Illuminate\Http\Request), Object(Closure))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\ValidatePostSize.php(27): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(180): Illuminate\Foundation\Http\Middleware\ValidatePostSize->handle(Object(Illuminate\Http\Request), Object(Closure))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance.php(99): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(180): Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance->handle(Object(Illuminate\Http\Request), Object(Closure))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Http\Middleware\HandleCors.php(62): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(180): Illuminate\Http\Middleware\HandleCors->handle(Object(Illuminate\Http\Request), Object(Closure))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Http\Middleware\TrustProxies.php(39): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(180): Illuminate\Http\Middleware\TrustProxies->handle(Object(Illuminate\Http\Request), Object(Closure))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(116): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php(175): Illuminate\Pipeline\Pipeline->then(Object(Closure))
D:\laragon\www\sekolahdigital\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php(144): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter(Object(Illuminate\Http\Request))
D:\laragon\www\sekolahdigital\public\index.php(51): Illuminate\Foundation\Http\Kernel->handle(Object(Illuminate\Http\Request))
{main}

I'm using laragon with .test pretty domain and laravel 10

Laravel 10

Your requirements could not be resolved to an installable set of packages.

Problem 1
- laravel-ready/license-server[1.0.1, ..., 1.2.7] require illuminate/support ^9.0 -> found illuminate/support[v9.0.0, ..., v9.52.6] but these were not loaded, likely because it conflicts with another require.
- Root composer.json requires laravel-ready/license-server * -> satisfiable by laravel-ready/license-server[1.0.1, ..., 1.2.7].

You can also try re-running composer require with an explicit version constraint, e.g. "composer require laravel-ready/license-server:*" to figure out if any version is installable, or "composer require laravel-ready/license-server:^2.1" if you know which you need.

i try install to Laravel 9.27.0

Your requirements could not be resolved to an installable set of packages.

Problem 1
- Root composer.json requires laravel-ready/license-server ^1.2 -> satisfiable by laravel-ready/license-server[1.2.4].
- laravel-ready/license-server 1.2.4 requires laravel/sanctum ^2.15 -> found laravel/sanctum[v2.15.0, v2.15.1, 2.x-dev] but it conflicts with your root
composer.json require (^3.0).

Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.

Installation failed, reverting ./composer.json and ./composer.lock to their original content.

Laravel 11

Your requirements could not be resolved to an installable set of packages.

Problem 1
- laravel-ready/license-server[1.0.1, ..., 1.2.7] require illuminate/support ^9.0 -> found illuminate/support[v9.0.0, ..., v9.52.16] but these were not loaded, likely because it conflicts with another require.
- laravel-ready/license-server 1.2.17 requires illuminate/support ^10.0 || ^9.0 -> found illuminate/support[v9.0.0, ..., v9.52.16, v10.0.0, ..., v10.48.9] but these were not loaded, likely because it conflicts with another require.
- Root composer.json requires laravel-ready/license-server * -> satisfiable by laravel-ready/license-server[1.0.1, ..., 1.2.17].

You can also try re-running composer require with an explicit version constraint, e.g. "composer require laravel-ready/license-server:*" to figure out if any version is installable, or "composer require laravel-ready/license-server:^2.1" if you know which you need.

How to work with subdomains

Hi,
My domain is domain.com! I tested with domain.com, WORKS!

I test with subdomain.domain.com and enable subdomain in config.

After license verification:
object(stdClass)#165 (2) { ["status"]=> bool(false) ["message"]=> string(38) "Invalid license key or license source." }

Please help me!

Best regards!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.