PHPackages                             esanj/app-service - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. esanj/app-service

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

esanj/app-service
=================

The AppService package facilitates external service connection based on client ID.

v0.0.21(3w ago)061MITPHPPHP ^8.2|^8.3|^8.4

Since Jul 29Pushed 3w agoCompare

[ Source](https://github.com/eSanjDev/ms-package-app-service)[ Packagist](https://packagist.org/packages/esanj/app-service)[ RSS](/packages/esanj-app-service/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (8)Versions (16)Used By (0)

Esanj App Service
=================

[](#esanj-app-service)

The **App Service** package is part of the Esanj microservice ecosystem. It lets a host application register external **services** (each identified by a `client_id`), assign **per‑service API permissions**, and validate incoming **JWT** requests from those services — through both a web admin panel and a JSON API.

**Supports:** Laravel 10 · 11 · 12 · 13 — PHP 8.2+

---

🧩 Features
----------

[](#-features)

- Register, list, update, soft‑delete, and restore services (web UI **and** API).
- Per‑service API permissions, importable from config.
- `service.validation` middleware — validates a service's JWT (RS256) and attaches its identity to the request.
- `service.permission:{key}` middleware — authorizes a service for a specific permission.
- API‑only mode for projects that don't need the UI.
- Integrates with **esanj/managers** (admin auth &amp; permissions) and **esanj/layout-master** (UI).

---

⚙️ Requirements
---------------

[](#️-requirements)

- **PHP** 8.2+
- **Laravel** 10–13
- **`esanj/managers`** — admin authentication &amp; the `manager.auth` / `manager.permission` middleware (required).
- **`esanj/auth-bridge`** — OAuth client credentials &amp; the public key used to verify service JWTs (required; installed automatically).
- **`esanj/layout-master`** — only for the **web UI** (the views extend its master layout). Not needed in [API‑only mode](#-api-only-mode).

---

🚀 Installation
--------------

[](#-installation)

```
composer require esanj/app-service
php artisan app-service:install
```

`app-service:install` will:

1. Publish the **assets** and **config** (`config/esanj/app_service.php`).
2. Ask to run **migrations** (creates `services`, `service_metas`, `service_permissions`, `service_permission_map`).
3. Import the **service permissions** (`app-service:permissions-import`).
4. Import the **manager permissions** (the `permissions` from this package's config) into `esanj/managers`.

> Steps 3–4 are skipped with a warning if the relevant tables don't exist yet — run `php artisan migrate` first, then re‑run the import commands.

---

🔧 Configuration
---------------

[](#-configuration)

The config file is `config/esanj/app_service.php` (merged under the key `esanj.app_service`).

KeyDefaultEnvDescription`routes.web_prefix``admin``APP_SERVICE_WEB_PREFIX`Prefix for the web panel routes.`routes.api_prefix``api``APP_SERVICE_API_PREFIX`Prefix for the API routes.`just_api``false``APP_SERVICE_JUST_API`API‑only mode (no web panel/views).`middlewares.web``['web', 'manager.auth:web']`—Middleware for the web panel.`middlewares.api``['api', 'manager.auth:api']`—Middleware for the management API.`permissions`4 `services.*` permissions—**Manager** permissions guarding the panel/management API.`service_permissions`5 `transactions.*` examples—**Service** permissions assignable to services.`access_provider`action → permission map—Which manager permission each controller action needs.`extra_fields``[]`—Blade views injected into the create/edit forms.> ℹ️ **Two kinds of permissions** — don't confuse them:
>
> - `permissions` (`services.list/create/update/delete`) gate **managers** using the admin panel/management API.
> - `service_permissions` (`transactions.*`, etc.) are granted to **services** and checked by `service.permission`.

---

🖥️ Web UI
---------

[](#️-web-ui)

Available when `just_api` is `false`. Visit `route('services.index')` (default `/admin/services`) to list, create, edit, delete, and restore services.

MethodURI (default)Route nameManager permissionGET`/admin/services``services.index``services.list`GET`/admin/services/create``services.create``services.create`POST`/admin/services``services.store``services.create`GET`/admin/services/{id}/edit``services.edit``services.update`PUT/PATCH`/admin/services/{id}``services.update``services.update`DELETE`/admin/services/{id}``services.destroy``services.delete`POST`/admin/services/{id}/restore``services.restore``services.delete`GET`/admin/services/validation``services.validation`(authenticated manager)---

🔗 Management API
----------------

[](#-management-api)

These endpoints **manage** service records and are guarded by `manager.auth:api` (a manager Bearer token from `esanj/managers`) plus the matching `services.*` manager permission.

MethodURI (default)Route nameManager permissionGET`/api/services``api.services.index``services.list`POST`/api/services``api.services.store``services.create`GET`/api/services/{id}``api.services.show``services.list`PUT/PATCH`/api/services/{id}``api.services.update``services.update`DELETE`/api/services/{id}``api.services.destroy``services.delete`POST`/api/services/{id}/restore``api.services.restore``services.delete`GET`/api/services/validation``api.services.validation`(manager auth)**Body for create/update:** `name` (required, unique), `client_id` (required, unique), `is_active` (boolean), `permissions` (array of **`service_permissions` IDs**).

---

🔐 Service permissions
---------------------

[](#-service-permissions)

Define the permissions your services can hold in `config/esanj/app_service.php`:

```
'service_permissions' => [
    'transactions.list' => [
        'display_name' => 'List Transactions',
        'description'  => 'Allows viewing the list of all transactions for the service',
    ],
    // ...
],
```

Import them into the database:

```
php artisan app-service:permissions-import
```

Then assign them to a service from the edit page, or via the API `permissions` array.

---

🧩 Middleware
------------

[](#-middleware)

### `service.validation` — validate a service JWT

[](#servicevalidation--validate-a-service-jwt)

Validates the `Authorization: Bearer {token}` JWT (RS256, verified with the auth‑bridge public key). On success it attaches to the request:

- `jwt_client_id` — the token's `aud` (audience) claim.
- `jwt_payload` — the full decoded payload.

On a missing/invalid/expired token it throws a `401 Unauthorized`.

### `service.permission:{key}` — authorize a service

[](#servicepermissionkey--authorize-a-service)

Checks that the calling service (identified from its JWT) is **active** and holds the given permission. **It validates the JWT itself**, so you don't have to chain `service.validation` before it.

```
// service.permission already validates the token, so this is enough:
Route::get('/transactions', [TransactionController::class, 'index'])
    ->middleware('service.permission:transactions.list');

// Add service.validation only if you also need $request->attributes 'jwt_payload' in the handler:
Route::get('/transactions', [TransactionController::class, 'index'])
    ->middleware(['service.validation', 'service.permission:transactions.list']);
```

---

🌐 API‑only mode
---------------

[](#-apionly-mode)

If you don't need the web panel:

```
APP_SERVICE_JUST_API=true
```

This disables the web routes and views; the API stays fully functional. In this mode `esanj/layout-master` is not required.

---

🎛️ Extending the forms
----------------------

[](#️-extending-the-forms)

Inject your own Blade views into the create/edit forms via config (each is `@include`‑d):

```
'extra_fields' => [
    'content.product',
],
```

---

📚 Documentation
---------------

[](#-documentation)

For a complete, beginner‑friendly, step‑by‑step walkthrough — registering a service, assigning permissions, protecting your own service API, adding a custom permission or form field, and troubleshooting — see **[docs/GUIDE.md](docs/GUIDE.md)**.

---

🪪 License
---------

[](#-license)

MIT — part of the Esanj ecosystem.

###  Health Score

43

—

FairBetter than 89% of packages

Maintenance95

Actively maintained with recent releases

Popularity10

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~22 days

Recently: every ~46 days

Total

15

Last Release

23d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/c908dfdf092a072c4bc678b161b053e20d00f90e9e9ba2c18ecddef6b848f1a4?d=identicon)[esanj](/maintainers/esanj)

---

Top Contributors

[![itsalifadaei](https://avatars.githubusercontent.com/u/34383343?v=4)](https://github.com/itsalifadaei "itsalifadaei (63 commits)")

### Embed Badge

![Health badge](/badges/esanj-app-service/health.svg)

```
[![Health](https://phpackages.com/badges/esanj-app-service/health.svg)](https://phpackages.com/packages/esanj-app-service)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M346](/packages/psalm-plugin-laravel)[illuminate/pipeline

The Illuminate Pipeline package.

9349.2M282](/packages/illuminate-pipeline)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
