michaelorenda/etherpad-client

A framework-agnostic PHP client for Etherpad API with session and permission handling.

Installs: 1

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/michaelorenda/etherpad-client

v1.2.0 2025-10-23 14:26 UTC

This package is auto-updated.

Last update: 2025-11-23 14:36:30 UTC


README

A framework-agnostic PHP library for integrating with the Etherpad collaborative editor API β€” complete with per-user pad permissions, ready for Laravel 12 or plain PHP 8.1+ projects.

πŸš€ What Is Etherpad?

Etherpad Lite is an open-source collaborative text editor.
It runs on Node.js and exposes a REST API for creating pads, managing sessions, and synchronizing text in real time.

This library provides a simple PHP interface to that API, and a permissions system for managing user access to pads in your own application.

🧩 Features

βœ… Full Etherpad API support (create, read, update, delete pads)
βœ… Laravel 12–ready via Service Provider βœ… Optional Eloquent integration for Laravel projects
βœ… Simple permissions table (pad_permissions) for managing who can view/edit
βœ… Framework-agnostic β€” works with or without Laravel
βœ… Includes SQL migration + auto table creation helper
βœ… Secure: uses PDO + prepared statements
βœ… MIT licensed for open use

βš™οΈ Installation

1. Install via Composer

Run this command in your project directory:

composer require michaelorenda/etherpad-client

2. Configure Etherpad

In your Etherpad installation (often /opt/etherpad-lite):

cat APIKEY.txt

Copy the key β€” you’ll need it in your .env.

Ensure Etherpad is accessible on a port (e.g. http://localhost:9001).

3. Add Environment Variables

In Laravel, add to your .env file:

ETHERPAD_API_URL=http://localhost:9001
ETHERPAD_API_KEY=your_api_key_here

For plain PHP, you’ll just use these values directly in your script.

🧱 Database Setup

This package includes a migration file for your permissions table.

Run manually in MySQL:

mysql -u youruser -p yourdatabase < vendor/michaelorenda/etherpad-client/database/migrations/create_pad_permissions_table.sql

Or in Laravel (optional):
You can copy the SQL contents into a migration file under database/migrations/ and run:

php artisan migrate

🧠 Understanding the Permissions Model

The table pad_permissions links users to Etherpad pads.
Each record defines whether a user can view or edit that pad.

Column Description
pad_id Etherpad pad identifier
user_id Your application’s user ID
can_edit 1 if user can edit
can_view 1 if user can view
created_at Timestamp of assignment

🧰 Laravel 12 Integration

Here’s how to make it work seamlessly inside Laravel.

Step 1: Create a Service Provider

Create file:
app/Providers/EtherpadServiceProvider.php

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use MichaelOrenda\Etherpad\EtherpadClient;
use MichaelOrenda\Etherpad\PadPermissionManager;
use PDO;

class EtherpadServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->singleton(EtherpadClient::class, function () {
            return new EtherpadClient(
                config('services.etherpad.url'),
                config('services.etherpad.key')
            );
        });

        $this->app->singleton(PadPermissionManager::class, function () {
            $pdo = new PDO(
                env('DB_CONNECTION') . ':host=' . env('DB_HOST') . ';dbname=' . env('DB_DATABASE'),
                env('DB_USERNAME'),
                env('DB_PASSWORD')
            );
            $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            return new PadPermissionManager($pdo);
        });
    }
}

Register the provider in config/app.php:

'providers' => [
    ...
    App\Providers\EtherpadServiceProvider::class,
],

Then in config/services.php, add:

'etherpad' => [
    'url' => env('ETHERPAD_API_URL'),
    'key' => env('ETHERPAD_API_KEY'),
],

Step 2: Create a Controller

app/Http/Controllers/PadController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use MichaelOrenda\Etherpad\EtherpadClient;
use MichaelOrenda\Etherpad\PadPermissionManager;

class PadController extends Controller
{
    protected $etherpad;
    protected $permissions;

    public function __construct(EtherpadClient $etherpad, PadPermissionManager $permissions)
    {
        $this->etherpad = $etherpad;
        $this->permissions = $permissions;
    }

    public function open(Request $request, string $padId)
    {
        $userId = $request->user()->id;

        // Check if user has permissions
        if ($this->permissions->canEdit($padId, $userId)) {
            $authorID = $this->etherpad->createAuthor($request->user()->name, (string)$userId);
            $groupID = $this->etherpad->createGroup();
            $sessionID = $this->etherpad->createSession($groupID, $authorID, time() + 3600);

            setcookie('sessionID', $sessionID, time() + 3600, '/', '', false, true);

            return redirect()->away(config('services.etherpad.url') . "/p/{$padId}");
        }

        if ($this->permissions->canView($padId, $userId)) {
            $readonlyID = $this->etherpad->getReadOnlyID($padId);
            return redirect()->away(config('services.etherpad.url') . "/p/{$readonlyID}");
        }

        abort(403, 'Access denied.');
    }

    public function grantEdit(int $userId, string $padId)
    {
        $this->permissions->grant($padId, $userId, true, true);
        return response()->json(['status' => 'granted']);
    }

    public function revokeAccess(int $userId, string $padId)
    {
        $this->permissions->revoke($padId, $userId);
        return response()->json(['status' => 'revoked']);
    }
}

Step 3: Add Routes

In routes/web.php:

use App\Http\Controllers\PadController;

Route::middleware(['auth'])->group(function () {
    Route::get('/pads/{padId}', [PadController::class, 'open']);
    Route::post('/pads/{padId}/grant/{userId}', [PadController::class, 'grantEdit']);
    Route::delete('/pads/{padId}/revoke/{userId}', [PadController::class, 'revokeAccess']);
});

πŸ§ͺ Example for Plain PHP Project

You can also use the library without Laravel.

require 'vendor/autoload.php';

use MichaelOrenda\Etherpad\EtherpadClient;
use MichaelOrenda\Etherpad\PadPermissionManager;

$etherpad = new EtherpadClient('http://localhost:9001', 'your_api_key_here');

$pdo = new PDO('mysql:host=localhost;dbname=mydb', 'user', 'pass');
$permissions = new PadPermissionManager($pdo);

// Create a new pad if needed
$groupId = $etherpad->createGroup();
$padId = $etherpad->createGroupPad($groupId, 'demoPad', 'Hello world');

// Grant a user edit rights
$permissions->grant($padId, 1, true, true);

// Check permissions
if ($permissions->canEdit($padId, 1)) {
    echo "User #1 can edit pad: $padId";
}

🧰 Using Permissions

1. Using PDO (Framework-agnostic)

use MichaelOrenda\Etherpad\PadPermissionManager;
use PDO;

$pdo = new PDO('mysql:host=localhost;dbname=mydb', 'user', 'pass');
$permissions = new PadPermissionManager($pdo);

// Grant a user edit permission
$permissions->grant($padId, $userId, true, true);

// Revoke a user
$permissions->revoke($padId, $userId);

// Check permissions
$permissions->canEdit($padId, $userId);
$permissions->canView($padId, $userId);

2. Using Eloquent (Laravel optional)

use MichaelOrenda\Etherpad\PadPermissionEloquent;

// Grant a user edit permission
PadPermissionEloquent::grant($padId, $userId, true, true);

// Revoke a user
PadPermissionEloquent::revoke($padId, $userId);

// Check permissions
PadPermissionEloquent::canEdit($padId, $userId);
PadPermissionEloquent::canView($padId, $userId);

// List users for a pad
$users = PadPermissionEloquent::listUsersForPad($padId);

// List pads for a user
$pads = PadPermissionEloquent::listPadsForUser($userId);

πŸ’‘ Tip: Use PDO if you want a framework-agnostic setup, or Eloquent for Laravel projects.

πŸ”’ Security Tips

  • Always protect your API key β€” never expose it to frontend code.
  • Use HTTPS between your PHP app and Etherpad.
  • Regularly rotate your Etherpad API key if shared between systems.
  • Sanitize pad IDs if you let users create them dynamically.

🧩 Common Troubleshooting

Issue Cause Fix
HTTP Request failed Etherpad not running or wrong port Check your Etherpad process and URL
Invalid API key APIKEY.txt mismatch Verify the contents match your .env
Pad opens read-only Permission table entry missing Use grant() before accessing pad
Access denied (403) User lacks can_view or can_edit Check pad_permissions table

🧰 Directory Overview

src/
 β”œβ”€β”€ EtherpadClient.php
 β”œβ”€β”€ PadPermissionManager.php
 └── Exceptions/
      └── EtherpadException.php

database/
 └── migrations/
      └── create_pad_permissions_table.sql

examples/
 └── open_pad.php

βœ… Summary

  • Use PadPermissionManager for PDO-based universal access
  • Use PadPermissionEloquent for Laravel ORM integration
  • Supports view and edit per-user permissions
  • Fully compatible with Laravel 12, or any PHP project

🧾 License

MIT License β€” free for personal and commercial use.
See LICENSE for details.

❀️ Credits

Developed by Michael Orenda
Built for developers who love clean, modular PHP integrations.